package test;



import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.internal.StringUtil;

import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

// 服务器类
public class GBT32960Serversss {


    // 整车数据 car
    private JSONObject realTimeInfo01(  ByteBuf in){
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("Status",in.readUnsignedByte()); // 车辆状态
        jsonObject.put("Charging",in.readUnsignedByte()); //充电状态
        jsonObject.put("Mode",in.readUnsignedByte());  // 模式
        jsonObject.put("Speed",in.readUnsignedShort()/10);  // 速度
        jsonObject.put("Mileage",in.readUnsignedInt()/10);  // 里程
        jsonObject.put("Voltage",in.readUnsignedShort()/10);// 总电压
        int c = in.readUnsignedShort();
        jsonObject.put("Current",c/10-1000); // 总电流
        jsonObject.put("SOC",in.readUnsignedByte());  //SOC
        jsonObject.put("DC",in.readUnsignedByte());  // DC-DC状态
        byte inputByte =  in.readByte();

        int hasDriveForce = (inputByte & 0b00100000);

        // 提取第4位（制动力）
        int hasBrakingForce = (inputByte & 0b00010000);

        // 提取档位信息（第0位到第3位）
        int gearPosition = inputByte & 0b00001111;

        jsonObject.put("drivingForce",hasDriveForce);  //挡位
        jsonObject.put("brakingForce",hasBrakingForce);  //挡位

        jsonObject.put("Gear",gearPosition);  //挡位
        jsonObject.put("Resistance",in.readUnsignedShort()); // 电阻
        jsonObject.put("Reserved",in.readUnsignedShort());  // 预留

        return jsonObject;

    }
//chargeableVoltageData  可充电储能装置电压数据
    private JSONObject realTimeInfo08(ByteBuf in) {
        JSONObject jsonObject = new JSONObject();
        short number = in.readUnsignedByte() ;
        jsonObject.put("chargeableNumber",number); // 可从点存能子系统个数

        JSONArray jsonArray = new JSONArray();

        for (int i = 0; i < number; i++) {
            JSONObject ccc = new JSONObject();
            ccc.put("ChargeableSubsysNo",in.readUnsignedByte()); //  可充电储能装置子系统号
            ccc.put("ChargeableVoltage",in.readUnsignedShort()/10); //可充电储能装置电压

            ccc.put("ChargeableCurrent",in.readUnsignedShort()/10-1000); // 可充电储能装置电流
            int CellsTotal = in.readUnsignedShort();
            ccc.put("CellsTotal",CellsTotal);  //   单体电池总数
            ccc.put("FrameCellsIndex",in.readUnsignedShort()); //本帧起始电池序号

            short FrameCellsCount = in.readUnsignedByte();
            ccc.put("FrameCellsCount",FrameCellsCount); // 本帧起始电池总数

            JSONArray jsonArray1 = new JSONArray();
            for (int i1 = 0; i1 < FrameCellsCount; i1++) {
                JSONObject cccc = new JSONObject();
                cccc.put("CellsVoltage", in.readUnsignedShort()/1000);
                jsonArray1.add(cccc);
            }
            ccc.put("CellsVoltageList",jsonArray1); //单体电池电压
            jsonArray.add(ccc);

        }
        jsonObject.put("chargeableSubSystems",jsonArray);

        return jsonObject;
    }
    //chargeableTempData  可充电储能装置温度数据
    private JSONObject realTimeInfo09(ByteBuf in) {
        JSONObject jsonObject = new JSONObject();
        short number = in.readUnsignedByte() ;
        jsonObject.put("chargeableNumber",number); // 可子系统个数

        JSONArray jsonArray = new JSONArray();

        for (int i = 0; i < number; i++) {
            JSONObject ccc = new JSONObject();
            ccc.put("ChargeableSubsysNo",in.readUnsignedByte()); // 子系统号
            int ProbeNum = in.readUnsignedShort();
            ccc.put("ProbeNum",ProbeNum); // 可充能储能温度探针数
            JSONArray jsonArray1 = new JSONArray();

            for (int i1 = 0; i1 < ProbeNum; i1++) {
                JSONObject cccc = new JSONObject();
                cccc.put("Temp", in.readUnsignedByte()-40);
                jsonArray1.add(cccc);
            }
            ccc.put("ProbeTemp",jsonArray1); //温度值
            jsonArray.add(ccc);

        }
        jsonObject.put("chargeableTempSubSystems",jsonArray);

        return jsonObject;
    }

    // // 驱动电机数据  motor
    private JSONArray realTimeInfo02(  ByteBuf in){
        JSONArray jsonArray = new JSONArray();
        int number =  in.readUnsignedByte();

        for (int i = 0; i < number; i++) {
            JSONObject jsonObject = new JSONObject();

            jsonObject.put("Number",number); // 驱动机个数
            int no = in.readUnsignedByte();
            jsonObject.put("no",no); // 驱动机序号
            jsonObject.put("state",in.readUnsignedByte());  // 驱动机电机状态
            jsonObject.put("CtrlTemp",in.readUnsignedByte()-40);  // 驱动电机控制器温度
            jsonObject.put("Rotating",(in.readUnsignedShort()-20000)/10);  // 转速
            jsonObject.put("Torque",in.readUnsignedShort()-20000);// 转距
            jsonObject.put("MotorTemp",in.readUnsignedByte()-40); // 电机温度
            jsonObject.put("InputVoltage",in.readUnsignedShort()/10);// 电机控制器输入电压
            jsonObject.put("DCBusCurrent",in.readUnsignedShort()/10-1000); // 电机控制器直流母线电流

            jsonArray.add(jsonObject);
        }
        return jsonArray;

    }

    // 燃料电池数据  fuelCell
    private JSONObject realTimeInfo03(  ByteBuf in){
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("Voltage",in.readUnsignedShort()/10); // 电压电流
        jsonObject.put("Current",in.readUnsignedShort()/10); //电流

        jsonObject.put("FuelConsumption",in.readUnsignedShort()/100); // 燃料消耗率
        int pnum = in.readUnsignedShort();
        jsonObject.put("ProbeNum",pnum); // 温度探针数量
//        List<Integer> tmps = new ArrayList<>();
        JSONArray ProbeTemps = new JSONArray();
        for (int i = 0; i < pnum; i++) {
            JSONObject jsonObject1 = new JSONObject();
            jsonObject1.put("Temp",(int)in.readUnsignedByte()-40);
            ProbeTemps.add(jsonObject1);
//            tmps.add((int)in.readByte());
        }
        jsonObject.put("ProbeTemp",ProbeTemps); // 探针温度值列表

        // 氢系统中最高温度 2
        jsonObject.put( "H_MaxTemp",  in.readUnsignedShort()/10-40);
        jsonObject.put( "H_TempProbeCode",(int)  in.readUnsignedByte()-40); // 氢系统中最高温度探针代号
        jsonObject.put( "H_MaxConc",  in.readUnsignedShort()); // 氢气最高浓度
        jsonObject.put( "H_ConcSensorCode", (int) in.readUnsignedByte()); // 氢气最高浓度传感器代号
        jsonObject.put( "H_MaxPress",  in.readUnsignedShort()/10); // 氢气最高压力
        jsonObject.put( "H_PressSensorCode", (int) in.readUnsignedByte()); // 氢气最高压力传感器代号
        jsonObject.put( "DCStatus",  in.readUnsignedByte()); // 高压DC/DC状态


        return jsonObject;

    }

    // 发动机数据  engine
    private JSONObject realTimeInfo04(  ByteBuf in){
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("Status",in.readUnsignedByte()); // 发动机状态
        jsonObject.put("CrankshaftSpeed",in.readUnsignedShort()); //曲轴转速
        jsonObject.put("FuelConsumption",in.readUnsignedShort()/100);  // 燃料消耗率
        return jsonObject;

    }

    // 车辆位置数据  location
    private JSONObject realTimeInfo05(  ByteBuf in){
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("Status",in.readUnsignedByte()); // 定位状态
        long lo = in.readUnsignedInt();
        long la = in.readUnsignedInt();
        jsonObject.put("Longitude",lo/ Math.pow(10, 6)); // 经度
        jsonObject.put("Latitude",la/ Math.pow(10, 6)); // 纬度

        jsonObject.put("CoordinateSystem",1); // 纬度
        jsonObject.put("Altitude",0); // 纬度


        return jsonObject;

    }

    // 极值数据  extreme
    private JSONObject realTimeInfo06(  ByteBuf in){
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("MaxVoltageBatterySubsysNo",in.readUnsignedByte()); // 最高电压电池子系统号
        jsonObject.put("MaxVoltageBatteryCode",in.readUnsignedByte()); //最高电压电池单体代号
        jsonObject.put("MaxBatteryVoltage",in.readUnsignedShort()/1000);  //电池单体电压最高值

        jsonObject.put("MinVoltageBatterySubsysNo",in.readUnsignedByte()); // 最低电压电池子系统号
        jsonObject.put("MinVoltageBatteryCode",in.readUnsignedByte()); //最低电压电池单体代号
        jsonObject.put("MinBatteryVoltage",in.readUnsignedShort()/1000);  // 电池单体电压最低值

        jsonObject.put("MaxTempSubsysNo",in.readUnsignedByte()); // 最高温度子系统号
        jsonObject.put("MaxTempProbeNo",in.readUnsignedByte()); //最高温度探针代号
        jsonObject.put("MaxTemp",in.readUnsignedByte()-40);  //最高温度

        jsonObject.put("MinTempSubsysNo",in.readUnsignedByte()); // 最低温度子系统号
        jsonObject.put("MinTempProbeNo",in.readUnsignedByte()); //最低温度探针代号
        jsonObject.put("MinTemp",in.readUnsignedByte()-40);  // 最低温度

        return jsonObject;

    }

  // 报警数据解析

    private final String[] alarmMap = new String[]{
      "温度差异",
      "电池高温",
      "车载储能装置类型过压",
      "车载储能装置类型欠压",
      "SOC低",
      "单体电池过压",
      "单体电池欠压",
      "SOC过高",
            "SOC跳变",
            "可充电储能系统不匹配",
            "电池单体一致性差","绝缘报警",
            "DC-DC温度报警",
            "制动系统报警",
            "DC-DC状态报警",
            "驱动电机控制器温度报警", "高压互锁状态报警","驱动电机温度报警","车载储能装置类型过充",

    };

    // 报警数据  alarm
    private JSONObject realTimeInfo07(  ByteBuf in){
        JSONObject jsonObject = new JSONObject();

        jsonObject.put("MaxAlarmLevel",(int)in.readUnsignedByte()); // 最高报警等级
        long GeneralAlarmFlag = in.readUnsignedInt();
        jsonObject.put("GeneralAlarmFlag",GeneralAlarmFlag); //通用报警标志
        List<String> alarmInfos = new ArrayList<>();
        for (int i = 0; i < 32; i++) {
            long bit = (GeneralAlarmFlag >> i) & 1;
            if (bit == 1 && i< alarmMap.length){
                // 当前位发生了报警
                String alarmInfo = alarmMap[i];
                alarmInfos.add(alarmInfo);
            }
        }
        jsonObject.put("GeneralAlarmInfos",JSON.toJSONString(alarmInfos)); //通用报警信息

        int count = in.readUnsignedByte();
        jsonObject.put("FaultChargeableDeviceNum",count);  // 可充电储能装置故障总数N
        List<Long> FaultChargeableDeviceList = new ArrayList<>();
        for (int i = 0; i < count; i++) {
            FaultChargeableDeviceList.add(in.readUnsignedInt());
        }
        jsonObject.put("FaultChargeableDeviceList",JSON.toJSONString(FaultChargeableDeviceList));  // 可充电储能装置故障代码列表
        int qcount = in.readByte();
        jsonObject.put("FaultDriveMotorNum",qcount);  // 驱动电机故障总数
        List<Long> FaultDriveMotorList = new ArrayList<>();
        for (int i = 0; i < qcount; i++) {
            FaultDriveMotorList.add(in.readUnsignedInt());
        }
        jsonObject.put("FaultDriveMotorList",JSON.toJSONString(FaultChargeableDeviceList));  //  驱动电机故障代码列表


        int fcount = in.readByte();
        jsonObject.put("FaultEngineNum",fcount);  // 发动机故障总数
        List<Long> FaultEngineList = new ArrayList<>();
        for (int i = 0; i < fcount; i++) {
            FaultEngineList.add(in.readUnsignedInt());
        }
        jsonObject.put("FaultEngineList",JSON.toJSONString(FaultChargeableDeviceList));  // 发动机故障总数代码列表

        int qtcount = in.readByte();
        jsonObject.put("FaultOthersNum",qtcount);  // 其他故障总数
        List<Long> FaultOthersList = new ArrayList<>();
        for (int i = 0; i < qtcount; i++) {
            FaultOthersList.add(in.readUnsignedInt());
        }
        jsonObject.put("FaultOthersList",JSON.toJSONString(FaultChargeableDeviceList));  //其他故障代码列表


        return jsonObject;

    }

    private byte[] encodeMessage(GBT32960Message message) {
        ByteBuffer buffer = ByteBuffer.allocate(24 + message.getLength() + 1);
        buffer.put(GBT32960Message.getStartBit());
        buffer.put(message.getCommandType().getValue());
        buffer.put((byte) message.getResponseTag().getValue());
        buffer.put(message.getVin());
        buffer.put(message.getEncryptionType().getValue());
        buffer.putShort((short) message.getLength());
        buffer.put(message.getData());
        buffer.put(message.getCheckSum());

        byte[] body =buffer.array();

        return body;
    }

    public static class RealTimeInfo {
        private String time;

        private String key;

        private Object data;

        private String codeName;

        private String code;

        public String getCodeName() {
            return codeName;
        }

        public void setCodeName(String codeName) {
            this.codeName = codeName;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public String getTime() {
            return time;
        }

        public void setTime(String time) {
            this.time = time;
        }

        public Object getData() {
            return data;
        }

        public void setData(Object data) {
            this.data = data;
        }

        public void setData(JSONObject data) {
            this.data = data;
        }
    }

    public JSONArray realTimeInfo(String vid,byte[] data1){
        List<RealTimeInfo> data = new ArrayList<>();
        ByteBuf in = Unpooled.copiedBuffer(data1);

        try {
            // 前6位时间
            int year =  in.readUnsignedByte();
            int month =  in.readUnsignedByte();
            int day =  in.readUnsignedByte();

            int hour =  in.readUnsignedByte();
            int min =  in.readUnsignedByte();
            int sec =  in.readUnsignedByte();

            while (in.readableBytes() > 0 ){
//                System.out.println(in.readableBytes() );
                try{
                    // 1 信息标识位
                    RealTimeInfo realTimeInfo = new RealTimeInfo();
                    short flag =  in.readUnsignedByte();
                    JSONObject body;
//                    System.out.println(flag);
                    switch (flag) {
                        case 0x01:
                            // 整车数据
                            body = realTimeInfo01(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("vehicleData");

                            realTimeInfo.setCode("car-vehicleData");
                            realTimeInfo.setCodeName("整车数据");
                            break;
                        case 0x02:
                            // 驱动电机数据
                            JSONArray j = realTimeInfo02(in);
                            realTimeInfo.setData(j);
                            realTimeInfo.setKey("motor");
                            realTimeInfo.setCode("car-motor");
                            realTimeInfo.setCodeName("驱动电机数据");
                            break;
                        case 0x03:
                            // 驱动电机数据
                            body = realTimeInfo03(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("fuelcell");
                            realTimeInfo.setCode("car-fuelCell");
                            realTimeInfo.setCodeName("燃料电池数据");
                            break;
                        case 0x04:
                            // 驱动电机数据
                            body = realTimeInfo04(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("engine");
                            realTimeInfo.setCode("car-engine");
                            realTimeInfo.setCodeName("发动机数据");
                            break;
                        case 0x05:
                            // 驱动电机数据
                            body = realTimeInfo05(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("GeoLocation");
                            realTimeInfo.setCode("GPS_NORMAL");
                            realTimeInfo.setCodeName("GPS");
                            break;
                        case 0x06:
                            // 驱动电机数据
                            body = realTimeInfo06(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("extreme");
                            realTimeInfo.setCode("car-extreme");
                            realTimeInfo.setCodeName("极值数据");
                            break;
                        case 0x07:
                            // 驱动电机数据
                            body = realTimeInfo07(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("alarm");
                            realTimeInfo.setCode("car-alarm");
                            realTimeInfo.setCodeName("报警数据");
                            break;
                        case 0x08:
                            // 驱动电机数据
                            body = realTimeInfo08(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("chargeableVoltageData");
                            realTimeInfo.setCode("car-chargeableVoltageData");
                            realTimeInfo.setCodeName("可充电储能装置电压数据");
                            break;
                        case 0x09:
                            // 驱动电机数据
                            body = realTimeInfo09(in);
                            realTimeInfo.setData(body);
                            realTimeInfo.setKey("chargeableTempData");
                            realTimeInfo.setCode("car-chargeableTempData");
                            realTimeInfo.setCodeName("可充电储能装置温度数据");
                            break;

                    }
                    if (flag != 0x0){
//                        System.out.println(JSON.toJSONString(realTimeInfo));
                        data.add(realTimeInfo);
                    }


                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }finally {
            in.release();
        }
        if (data.size() >0){

//            JSONObject oneData = new JSONObject();
//            JSONObject props = new JSONObject();
//
//
//            oneData.put("props",props);
//
//            JSONObject metaData = new JSONObject();
//            metaData.put("sn",vid);
//            metaData.put("deviceName",vid);
//            metaData.put("code","car");
//            oneData.put("metadata",metaData);
//
//            JSONObject car = new JSONObject();
//            car.put("name","电动车");
//            JSONObject carProps = new JSONObject();
//            car.put("props",carProps);
//            for (RealTimeInfo datum : data) {
//                JSONObject curData = new JSONObject();
//                curData.put("name",datum.getKey());
//                curData.put("props",datum.getData());
//                carProps.put(datum.getKey(),curData);
//                props.put(datum.getKey(),curData);
//            }
            JSONArray jsonArray = new JSONArray();
//            List list1 = new ArrayList();
//            List list2 = new ArrayList();
            for (RealTimeInfo datum : data) {
                if (datum.getKey() == null){
                    continue;
                }
                if (!datum.getKey().equals("GeoLocation")){
//                    list1.add(datum);
                    jsonArray.add(oneData2(vid+datum.getCode(),vid,datum.getCode(),datum.getCodeName(), Arrays.asList(datum)));
                }else {
                    jsonArray.add(oneData2(vid+"GeoLocation",vid,"GPS_NORMAL","电动车定位",  Arrays.asList(datum)));
                }

            }


//            jsonArray.add(oneData(vid,null,"car","电动车", list1));
//            List list = data.stream().filter(i->i.getKey().equals("GeoLocation")).toList();
//            if (list2.size() >0){
//                jsonArray.add(oneData2(vid+"GeoLocation",vid,"GPS_NORMAL","电动车定位", list2));
//            }

            return jsonArray;
        }else {
            return null;
        }
    }

    private JSONObject oneData(String sn,String parseSn,String code,String name,List<RealTimeInfo> data){
        JSONObject oneData = new JSONObject();
        JSONObject props = new JSONObject();


        oneData.put("props",props);

        JSONObject metaData = new JSONObject();
        metaData.put("sn",sn);
        metaData.put("deviceName",sn);
        metaData.put("code",code);
        if (parseSn != null){
            metaData.put("parentSn",parseSn);

        }
        oneData.put("metadata",metaData);

        System.currentTimeMillis();

        JSONObject car = new JSONObject();
        car.put("name",name);
        JSONObject carProps = new JSONObject();
        car.put("props",carProps);
        for (RealTimeInfo datum : data) {
            JSONObject curData = new JSONObject();
            curData.put("name",datum.getKey());
            curData.put("props",datum.getData());
            carProps.put(datum.getKey(),curData);

        }
        props.put("car",car);
        return oneData;
    }

    private JSONObject oneData2(String sn,String parseSn,String code,String name,List<RealTimeInfo> data){
        JSONObject oneData = new JSONObject();
        JSONObject props = new JSONObject();


        oneData.put("props",props);

        JSONObject metaData = new JSONObject();
        metaData.put("sn",sn);
        metaData.put("deviceName",sn);
        metaData.put("code",code);
        if (parseSn != null){
            metaData.put("parentSn",parseSn);

        }
        oneData.put("metadata",metaData);

        System.currentTimeMillis();

        JSONObject car = new JSONObject();
        car.put("name",name);
        JSONObject carProps = new JSONObject();
        car.put("props",carProps);
        for (RealTimeInfo datum : data) {
            JSONObject curData = new JSONObject();
            curData.put("name",datum.getKey());
            curData.put("props",datum.getData());
//            props.put("name",datum.getKey());
            props.put(datum.getKey(),curData);

        }
//        props.put(code,car);

        return oneData;
    }

    public Object protocolToDeviceData(byte[] cmd){

         return    ByteBufUtil.decodeHexDump(new String(cmd));
    }

    public Object deviceDataToProtocol(byte[] data){
        ByteBuf in = Unpooled.copiedBuffer(data);
        System.out.println(ByteBufUtil.hexDump(data));
        try{
            byte[] startBit = new byte[2];
            in.readBytes(startBit);
            if (startBit[0] != 0x23 || startBit[1] != 0x23) {
                return null;
            }

            short commandTypeByte = in.readUnsignedByte();
            short responseTagByte = in.readUnsignedByte();
            byte[] vin = new byte[17];
            in.readBytes(vin);
            short encryptionTypeShort = in.readUnsignedByte();
            int length = in.readUnsignedShort();

            if (in.readableBytes() < length + 1) {
                in.resetReaderIndex();
                return null;
            }

            byte[] data1 = new byte[length];
            in.readBytes(data1);
            CommandType commandType = CommandType.valuesOf(commandTypeByte);
            ResponseTag responseTag = ResponseTag.valuesOf(responseTagByte);
            EncryptionType encryptionType = EncryptionType.fromShort(encryptionTypeShort);

            GBT32960Message message = new GBT32960Message(commandType, responseTag, vin, encryptionType, length, data1);

            JSONArray jsonObject = null;
//            System.out.println(message.getCommandType().name());
            switch (message.getCommandType()) {
                case CAR_LOGIN:
                    break;
                case REAL_TIME_INFORMATION:
                    jsonObject =  realTimeInfo(new String(message.getVin()),message.getData());
                    break;
                case REAL_TIME_INFORMATION_TOO:
                    jsonObject =  realTimeInfo(new String(message.getVin()),message.getData());
                    break;
                case CAR_LOGIN_OUT:
                    break;
            }

//            System.out.println(JSON.toJSONString(jsonObject));

            byte[] srcData = encodeMessage(message);
//            iot.platform.device.gb32960.platform.PlatformService.PLATFORM.sendMessage(new String(message.getVin()),srcData);;
            message.setResponseTag(ResponseTag.SUCCESS);
            message.calculateChecksum();

            if (jsonObject == null){
                jsonObject = new JSONArray();
                JSONObject metaData = new JSONObject();
                metaData.put("sn",new String(message.getVin()));
                metaData.put("deviceName",new String(message.getVin()));
                metaData.put("code","car");
                JSONObject dd = new JSONObject();
                dd.put("metadata",metaData);
                jsonObject.add(dd);
            }
            jsonObject.getJSONObject(0).put("replay",  ByteBufUtil.hexDump(encodeMessage(message)));
            System.out.println(jsonObject);
            return jsonObject;
        }catch (Exception e){
            e.printStackTrace();

            return null;
        } finally {
            in.release();
        }

    }

}

// 枚举类定义
enum CommandType {

    CAR_LOGIN((short) 1, "车辆登入"),

    REAL_TIME_INFORMATION((short) 2, "实时上报"),

    REAL_TIME_INFORMATION_TOO((short) 3, "实时补发上报"),

    CAR_LOGIN_OUT((short) 4, "车辆登出"),


    PLATFORM_LOGIN((short) 5, "车辆登出"),

    PLATFORM_LOGOUT((short) 6, "车辆登出"),

    HEARTBEAT((short) 7, "心跳")
    ;

    private final short value;
    private final String description;

    CommandType(short value, String description) {
        this.value = value;
        this.description = description;
    }


    public byte getValue() {
        return (byte) value;
    }

    public String getDescription() {
        return description;
    }

    public static CommandType fromByte(byte value) {
        for (CommandType type : CommandType.values()) {
            if (type.value == value) {
                return type;
            }
        }
        throw new IllegalArgumentException("Unknown CommandType value: " + value);
    }
    public static CommandType valuesOf(Short value) {
        for (CommandType type : CommandType.values()) {
            if (type.value == value.shortValue()) {
                return type;
            }
        }
        throw new IllegalArgumentException("Unknown CommandType value: " + value);
    }

}

enum ResponseTag {
    SUCCESS((short) 1, "Success"),
    FAILURE((short) 2, "Failure"),

    COMMAND((short)254,"表示数据包为命令包"),
    ;

    private final short value;
    private final String description;

    ResponseTag(short value, String description) {
        this.value = value;
        this.description = description;
    }

    public static ResponseTag valuesOf(Short value) {
        for (ResponseTag type : ResponseTag.values()) {
            if (type.value == value) {
                return type;
            }
        }
        throw new IllegalArgumentException("Unknown CommandType value: " + value);
    }

    public short getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }

    public static ResponseTag fromByte(byte value) {
        for (ResponseTag tag : ResponseTag.values()) {
            if (tag.value == value) {
                return tag;
            }
        }
        throw new IllegalArgumentException("Unknown ResponseTag value: " + value);
    }
}

enum EncryptionType {
    NONE((byte) 0x01, "None"),
    RSA((byte) 0x02, "RSA"),
    AES((byte) 0x03, "AES");

    private final byte value;
    private final String description;

    EncryptionType(byte value, String description) {
        this.value = value;
        this.description = description;
    }

    public byte getValue() {
        return value;
    }

    public String getDescription() {
        return description;
    }

    public static EncryptionType fromShort(short value) {
        for (EncryptionType type : EncryptionType.values()) {
            if (type.value == value) {
                return type;
            }
        }
        throw new IllegalArgumentException("Unknown EncryptionType value: " + value);
    }
}

// 消息类定义
class GBT32960Message {
    private static final byte[] START_BIT = new byte[]{0x23, 0x23};
    private CommandType commandType;
    private ResponseTag responseTag;
    private byte[] vin;
    private EncryptionType encryptionType;
    private int length;
    private byte[] data;
    private byte checkSum;

    public GBT32960Message(CommandType commandType, ResponseTag responseTag, byte[] vin, EncryptionType encryptionType, int length, byte[] data) {
        this.commandType = commandType;
        this.responseTag = responseTag;
        this.vin = vin;
        this.encryptionType = encryptionType;
        this.length = length;
        this.data = data;
    }

    public void setCheckSum(byte checkSum) {
        this.checkSum = checkSum;
    }

    public void calculateChecksum() {
//        CommandType.REAL_TIME_INFORMATION.getValue(), ResponseTag.SUCCESS.getValue(), vin, EncryptionType.NONE.getValue(), data.length
        this.checkSum =calculateChecksum(START_BIT,this.commandType.getValue(),(byte) this.responseTag.getValue(),vin,encryptionType.getValue(),this.data.length,this.data);
    }
    private byte calculateChecksum(byte[] startBit, byte commandType, byte responseTag, byte[] vin, byte encryptionType, int length, byte[] data) {
        byte sum = 0;
        for (byte b : startBit) {
            sum ^= b;
        }
        sum ^= commandType;
        sum ^= responseTag;
        for (byte b : vin) {
            sum ^= b;
        }
        sum ^= encryptionType;
        sum ^= length;
        for (byte b : data) {
            sum ^= b;
        }
        return sum;
    }

    /**
     * BCC校验(异或校验)
     * @param byteBuf
     * @return
     */
    public static byte signBcc(ByteBuf byteBuf) {
        byte cs = 0;
        while (byteBuf.isReadable()){
            cs ^= byteBuf.readByte();
        }
        byteBuf.resetReaderIndex();
        return cs;
    }


    public static byte[] getStartBit() {
        return START_BIT;
    }

    public CommandType getCommandType() {
        return commandType;
    }

    public ResponseTag getResponseTag() {
        return responseTag;
    }

    public void setResponseTag(ResponseTag responseTag) {
        this.responseTag = responseTag;
    }

    public byte[] getVin() {
        return vin;
    }

    public EncryptionType getEncryptionType() {
        return encryptionType;
    }

    public int getLength() {
        return length;
    }

    public byte[] getData() {
        return data;
    }

    public byte getCheckSum() {
        return checkSum;
    }
}



